/*
@hehung
2023-2-8
转载请注明出处，版权由@hehung所有
email: 1398660197@qq.com
wechat: hehung95
*/

/**
RX - P102
TX - P103
**/

#include "hal_data.h"
#include "app_can.h"

#define CAN_DEBUG

#ifdef CAN_DEBUG
#include <stdio.h>
#endif

/***********************************************************************************************************************
 * Macro definitions
 **********************************************************************************************************************/
#define WAIT_TIME                       (5000U)            //wait time value
#define CAN_DESTINATION_MAILBOX_3       (3U)               //destination mail box number
#define CAN_MAILBOX_NUMBER_0            (0U)               //mail box number
#define CAN_FRAME_TRANSMIT_DATA_BYTES   (8U)               //data length
#define ZERO                            (0U)
#define NULL_CHAR                       ('\0')

#define RESET_VALUE             (0x00)
 #define BUFFER_SIZE_DOWN                          (16)

/***********************************************************************************************************************
 * Private global variables
 **********************************************************************************************************************/
/* Flags, set from Callback function */
static volatile bool b_can_tx = false;                  //CAN transmission status
static volatile bool b_can_rx = false;                  //CAN receive status
static volatile bool b_can_err = false;                 //CAN error status
/* CAN frames for tx and rx */
static can_frame_t g_can_tx_frame;      //CAN transmit frame
static can_frame_t g_can_rx_frame;      //CAN receive frame

    
uint32_t time_out = WAIT_TIME;                                      // time out
fsp_pack_version_t version = {RESET_VALUE};
uint8_t can_tx_msg[CAN_FRAME_TRANSMIT_DATA_BYTES] = "TX__MESG";       //data to be load in tx_frame while transmitting
uint8_t can_rx_msg[CAN_FRAME_TRANSMIT_DATA_BYTES] = "RX__MESG";       //data to be load in rx_frame while acknowledging
char rtt_input_buf[BUFFER_SIZE_DOWN] = {1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0};

// notification function of can0
void can0_notification(can_callback_args_t * p_args)
{

    switch (p_args->event)
    {
        case CAN_EVENT_TX_COMPLETE:
        {
            b_can_tx = true;        //set flag bit
            break;
        }

        case CAN_EVENT_RX_COMPLETE:
        {
            b_can_rx = true;
            memcpy(&g_can_rx_frame, &p_args->frame, sizeof(can_frame_t));  //copy the received data to rx_frame
            break;
        }

        case CAN_EVENT_MAILBOX_MESSAGE_LOST:    //overwrite/overrun error event
        case CAN_EVENT_BUS_RECOVERY:            //Bus recovery error event
        case CAN_EVENT_ERR_BUS_OFF:             //error Bus Off event
        case CAN_EVENT_ERR_PASSIVE:             //error passive event
        case CAN_EVENT_ERR_WARNING:             //error warning event
        case CAN_EVENT_ERR_BUS_LOCK:            //error bus lock
        case CAN_EVENT_ERR_CHANNEL:             //error channel
        case CAN_EVENT_ERR_GLOBAL:              //error global
        case CAN_EVENT_TX_ABORTED:              //error transmit abort
        case CAN_EVENT_TX_FIFO_EMPTY:           //error transmit FIFO is empty
        {
            b_can_err = true;                   //set flag bit
            break;
        }

    }

}

void Can_Deinit(void)
{
    fsp_err_t err = FSP_SUCCESS;

    err = R_CAN_Close(&g_can0_ctrl);
    if (FSP_SUCCESS != err)
    {
#ifdef CAN_DEBUG
        printf("CAN Close API failed\n");
#endif
    }
}

// initialzie the CAN module
void Can_Init(void)
{
    fsp_err_t err = FSP_SUCCESS;

    err = R_CAN_Open(&g_can0_ctrl, &g_can0_cfg);
    if(FSP_SUCCESS != err)
    {
#ifdef CAN_DEBUG
        printf("CAN Open API failed\n");
#endif 
    }

    g_can_tx_frame.id = CAN_DESTINATION_MAILBOX_3;
    g_can_tx_frame.type = CAN_FRAME_TYPE_DATA;
    g_can_tx_frame.data_length_code = CAN_FRAME_TRANSMIT_DATA_BYTES;

    /* copy the tx data frame with TX_MSG */
    memcpy((uint8_t*)&g_can_tx_frame.data[ZERO], (uint8_t*)&can_tx_msg[ZERO], CAN_FRAME_TRANSMIT_DATA_BYTES);

}


void Can_RunningEntry(void)
{
	fsp_err_t err = FSP_SUCCESS;
    int a;
	
    scanf("%d", &a);
    if (a == 1)
    {
        printf("\r\n Transmitting the data");

        /* transmit the data from mail box #0 with tx_frame */
        err = R_CAN_Write(&g_can0_ctrl, CAN_MAILBOX_NUMBER_0, &g_can_tx_frame);
        /* Error trap */
        if (FSP_SUCCESS != err)
        {
            printf("\r\n CAN Write API FAILED");
            Can_Deinit();
            
        }

        /* wait for transmit flag bit to set */
        while ((true != b_can_tx) && (--time_out));
        if (RESET_VALUE == time_out)
        {
            printf("CAN transmission failed due to timeout");
            
        }
        /* Reset flag bit */
        b_can_tx = false;
        printf("\r\n CAN transmission is successful");
        printf("\r\n To start CAN transmission, please enter any key on RTTViewer\n");
        memset(rtt_input_buf,NULL_CHAR,BUFFER_SIZE_DOWN);
    }


    /* check if receive flag is set */
    if (true == b_can_rx)
    {
        /* Reset flag bit */
        b_can_rx = false;
        printf("\r\n CAN received the data : %s\r\n", &g_can_rx_frame.data[0]);

        /* if received data is same as transmitted data then acknowledge with RX_MSG as received successful*/
        //if (RESET_VALUE == strncmp((char*)&g_can_rx_frame.data[ZERO], (char*)&can_tx_msg[ZERO], CAN_FRAME_TRANSMIT_DATA_BYTES))
        if (1)
        {
            printf("\r\n Received 'TX__MESG', responding with 'RX__MESG'\r\n");
            g_can_rx_frame.id = CAN_DESTINATION_MAILBOX_3;
            g_can_rx_frame.type = CAN_FRAME_TYPE_DATA;
            g_can_rx_frame.data_length_code = CAN_FRAME_TRANSMIT_DATA_BYTES;

            /* copy the rx_data frame as RX_MSG */
            //memcpy((uint8_t*)&g_can_rx_frame.data[ZERO], (uint8_t*)&can_rx_msg[ZERO], CAN_FRAME_TRANSMIT_DATA_BYTES);

            /* Transmit the rx data frame as acknowledging the data transfer is successful */
            err = R_CAN_Write (&g_can0_ctrl, CAN_MAILBOX_NUMBER_0, &g_can_rx_frame);
            /* Error trap */
            if (FSP_SUCCESS != err)
            {
                printf("\r\n CAN Write API FAILED");
                Can_Deinit();
                
            }
            /* wait for transmit flag bit to set */
            while ((true != b_can_tx) && (--time_out));
            if (RESET_VALUE == time_out)
            {
                printf("CAN transmission failed due to timeout");
                
            }
            printf("\r\n CAN transmission after receive is successful");
            /* Reset flag bit */
            b_can_tx = false;

        }
        /* check if received data is same as rx_msg then received an acknowledge for the transfer of data successful */
        else if (RESET_VALUE == strncmp((char*)&g_can_rx_frame.data[ZERO],(char*)&can_rx_msg[ZERO], CAN_FRAME_TRANSMIT_DATA_BYTES))
        {
            printf("\r\n Received Acknowledge.\r\n CAN operation Successful\r\n");
        }
        /* if no data match then data transfer failed */
        else
        {
            printf("\r\nCAN data mismatch\r\n CAN operation failed\r\n");
            
        }
        /* Reset the rx frame data */
        memset((uint8_t*)&g_can_rx_frame.data[ZERO],RESET_VALUE,CAN_FRAME_TRANSMIT_DATA_BYTES);
    }
    /* re initializing time out value */
    time_out = WAIT_TIME; 
}

